package com.fishery.authority.config;

import com.fishery.authority.filter.TokenAuthenticationFilter;
import com.fishery.authority.mapper.FunctionMapper;
import com.fishery.authority.security.DefaultPasswordEncoder;
import com.fishery.authority.security.MobileAuthenticationProvider;
import com.fishery.authority.security.TokenLogoutHandler;
import com.fishery.authority.security.UnauthorizedEntryPoint;
import com.fishery.authority.service.FunctionRoleService;
import com.fishery.authority.service.FunctionService;
import com.fishery.authority.service.UserRoleService;
import com.fishery.authority.service.UserService;
import com.fishery.authority.service.impl.UserDetailsServiceImpl;
import com.fishery.util.TokenManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * 安全配置类
 */
@Configuration
/**
 * 开启Spring Secuity的核心过滤器, 这是请求的认证入口
 * 激活AuthenticationConfiguration配置类，建造AuthenticationManager身份认证
 */
@EnableWebSecurity
/**
 * 解锁 @PreAuthorize 和 @PostAuthorize 两个注解。
 * @PreAuthorize 注解会在方法执行前进行验证
 * @PostAuthorize 注解会在方法执行后进行验证。
 */
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private TokenManager tokenManager;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private FunctionService functionService;

    @Resource
    private FunctionRoleService functionRoleService;

    @Resource
    private UserRoleService userRoleService;

    @Resource
    private UserService userService;

    @Resource
    private FunctionMapper functionMapper;

    @Autowired
    MobileAuthenticationProvider mobileAuthenticationProvider;

    @Autowired
    UserDetailsServiceImpl userDetailsService;


    @Autowired
    public WebSecurityConfig(UserDetailsServiceImpl userDetailsService, MobileAuthenticationProvider mobileAuthenticationProvider){
        this.userDetailsService=userDetailsService;
        this.mobileAuthenticationProvider=mobileAuthenticationProvider;
    }

    @Override
    @Bean
    //注入authenticationManager
    protected AuthenticationManager authenticationManager() throws Exception {
        DaoAuthenticationProvider dao1 = new DaoAuthenticationProvider();
        dao1.setUserDetailsService(userDetailsService);
        dao1.setPasswordEncoder(new DefaultPasswordEncoder());
        List<AuthenticationProvider> providers =new ArrayList();
        providers.add(mobileAuthenticationProvider);
        providers.add(dao1);
        ProviderManager manager = new ProviderManager(providers);
        return manager;
    }




    /**
     * 配置设置
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.exceptionHandling()
                .authenticationEntryPoint(new UnauthorizedEntryPoint())
                .and().cors()
                .and().csrf().disable()
                .authorizeRequests()
                //不用认证
                .antMatchers("/authority/user/login",
                        "/authority/user/register",
                        "/admin/login",
                        "/authority/user/loginByPhone",
                        "/captcha/**",
                        "/authority/user/retrievePassword",
                        "/authority/user/retrievePassword/**")
                .permitAll()
                .antMatchers(HttpMethod.OPTIONS)
                .permitAll()
                .anyRequest().authenticated()
                .and().logout().logoutUrl("/admin/index/logout")
                .addLogoutHandler(new TokenLogoutHandler(tokenManager,redisTemplate)).and()
//                .addFilter(new TokenLoginFilter(authenticationManager(), tokenManager, redisTemplate))
                .addFilter(new TokenAuthenticationFilter(
                        authenticationManager(),
                        tokenManager,
                        redisTemplate,
                        functionService,
                        userRoleService,
                        userService,
                        functionRoleService,
                        functionMapper)).httpBasic();
//                .addFilter(new TokenAuthenticationFilter(authenticationManager())).httpBasic();
    }

//    /**
//     * 密码处理
//     * @param auth
//     * @throws Exception
//     */
//    @Override
//    public void configure(AuthenticationManagerBuilder auth) throws Exception {
//        auth.userDetailsService(userDetailsService).passwordEncoder(defaultPasswordEncoder);
//    }

    /**
     * 配置哪些请求不拦截
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().
                antMatchers("/api/**",
                        "/swagger-resources/**",
                        "/webjars/**",
                        "/v2/**",
                        "/swagger-ui.html/**"
                );
//        web.ignoring().antMatchers("/*/**");
    }
}